﻿namespace Sai.Core
{
	using System;
	using System.Xml;
	using System.Xml.Serialization;

	/// <summary>
	/// One individual assembly in a product release.
	/// </summary>
	[XmlRoot("Assembly")]
	public sealed class ProductAssembly : IEquatable<ProductAssembly>
	{
		private Identifier ident = new Identifier();

		public ProductAssembly()
		{
		}

		public ProductAssembly(string path)
			: this(path, DateTime.MinValue, 0, string.Empty)
		{
		}

		public ProductAssembly(string path, DateTime date, long size, string checksum)
		{
			this.Path = path;
			this.Checksum = checksum;
			this.Date = date;
			this.Name = System.IO.Path.GetFileName(path);
			this.Size = size;
		}

		[XmlAttribute("ID")]
		public string Identifier
		{
			get
			{
				return this.ident.Value;
			}

			set
			{
				this.ident = new Identifier(value);
			}
		}

		[XmlAttribute("Name")]
		public string Name { get; set; }

		[XmlIgnore]
		public string Path { get; set; }

		[XmlIgnore]
		public DateTime Date { get; private set; }

		[XmlIgnore]
		public long Size { get; private set; }

		[XmlIgnore]
		public string Checksum { get; private set; }

		/// <summary>
		/// Equal based on everything but path.
		/// </summary>
		/// <param name="a">left hand side of comparison</param>
		/// <param name="b">right hand side of comparison</param>
		/// <returns>true if equal</returns>
		public static bool operator ==(ProductAssembly a, ProductAssembly b)
		{
			if (object.ReferenceEquals(a, b))
			{
				return true;
			}

			if (((object)a == null) || ((object)b == null))
			{
				return false;
			}

			return a.Name == b.Name && a.Size == b.Size && a.Date == b.Date && a.Checksum == b.Checksum;
		}

		public static bool operator !=(ProductAssembly a, ProductAssembly b)
		{
			return !(a == b);
		}

		public override string ToString()
		{
			return this.Name;
		}

		public override int GetHashCode()
		{
			return this.Checksum.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}

			ProductAssembly info = obj as ProductAssembly;

			if ((object)info == null)
			{
				return false;
			}

			return this.Name == info.Name
				&& this.Size == info.Size
				&& this.Date == info.Date
				&& this.Checksum == info.Checksum;
		}

		public bool Equals(ProductAssembly other)
		{
			if ((object)other == null)
			{
				return false;
			}

			return this.Name == other.Name
				&& this.Size == other.Size
				&& this.Date == other.Date
				&& this.Checksum == other.Checksum;
		} 
	}
}
